﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Camera
{

    class Camera
    {

        GraphicsDevice device;
        public Matrix vista; //matriz de visualizacao
        public Matrix projecao;
        public Vector3 cameraPos; //posicao da camera
        public Vector3 alvo; //para onde a camera está apontando
        public Vector3 orientacao; //a direção para onde a parte de cima da camera vai estar apontada
        public Vector3 DistanciaJogador;
        public Vector3 DistanciaAlvo;
        public float anguloAbertura;
        public float RazaoTela; //largura do espaço da vista dividido pela altura
        public float PlanoPerto; //minima distancia da camera para ser renderizada
        public float PlanoLonge; //maxima distancia da camera para ser renderizada

        public Vector3 PosicaoCamera
        {

            get
            {

                return cameraPos;

            }

            set
            {

                cameraPos = value;

            }

        }

        public Vector3 Alvo
        {

            get
            {

                return alvo;

            }

            set
            {

                alvo = value;

            }

        }

        public Vector3 Orientacao
        {

            get
            {

                return orientacao;

            }

            set
            {

                orientacao = value;

            }

        }

        public Camera()
        {

            PosicaoCamera = new Vector3(10, 10, 10);
            Alvo = Vector3.Zero;
            Orientacao = Vector3.Up;

            anguloAbertura = 45;
            RazaoTela = 4 / 3;
            PlanoPerto = 1;
            PlanoLonge = 100;

            DistanciaJogador = Vector3.Zero;//sugestao:(0,10,-15)
            DistanciaAlvo = Vector3.Zero;//sugestao: (0,5,0)

            vista = Matrix.CreateLookAt(cameraPos, alvo, orientacao);

            projecao = Matrix.CreatePerspectiveFieldOfView(
                MathHelper.ToRadians(anguloAbertura),
                RazaoTela,
                PlanoPerto,
                PlanoLonge);

        }

        public Camera(GraphicsDevice device, Vector3 cameraPos)
        {

            this.cameraPos = cameraPos;
            this.device = device;
            this.alvo = Vector3.Zero; //alvo no centro da tela
            this.orientacao = Vector3.Up; //orientacao normal, do jeito que a nossa querida Terra é

            this.vista = Matrix.CreateLookAt(//Camera
                this.cameraPos,
                this.alvo,
                this.orientacao);

            this.projecao = Matrix.CreatePerspectiveFieldOfView(//PROJECAO/TELA
                MathHelper.PiOver4,//abertura
                device.Viewport.AspectRatio,//proporcao/razao
                0.1f,//perto - minima distancia da camera para ser renderizada
                100.0f);//longe - maxima distancia da camera para ser renderizada

        }

        public void Update(GameTime gameTime, KeyboardState teclado, KeyboardState teclado_anterior, Matrix mundo, Vector3 novaCameraPos)
        {

            this.cameraPos = novaCameraPos;

            this.vista = Matrix.CreateLookAt(
                this.cameraPos,
                Vector3.Zero,
                Vector3.Up);

            this.projecao = Matrix.CreatePerspectiveFieldOfView(
                MathHelper.PiOver4,
                device.Viewport.AspectRatio,
                0.1f,
                100.0f);

            if (teclado.IsKeyDown(Keys.G))//fazer girar
            {

                mundo *= Matrix.CreateRotationY(MathHelper.Pi / 16);

            }

        }

        public void RotacionarCamera(float anguloRotacao, Vector3 _posicao)
        {

            Matrix matrizRotacao = Matrix.CreateRotationY(anguloRotacao);

            Vector3 distanciaCorrigida = Vector3.Transform(DistanciaJogador, matrizRotacao);
            Vector3 alvoCorrigido = Vector3.Transform(DistanciaAlvo, matrizRotacao);

            cameraPos = _posicao + distanciaCorrigida;
            alvo = _posicao + alvoCorrigido;

            vista = Matrix.CreateLookAt(cameraPos, alvo, orientacao);

            projecao = Matrix.CreatePerspectiveFieldOfView(
                MathHelper.ToRadians(anguloAbertura),
                RazaoTela,
                PlanoPerto,
                PlanoLonge);

        }

    }
}
